Cargar librerías

# Cargamos tidyverse
library("tidyverse")

Importar datos

# Cargamos datos
read_delim(
  file = "data/winequality-red.csv",
  delim = ",", 
  locale=locale(decimal_mark = ".")
  ) -> wine_raw

## Revisar la estructura de los datos
str(wine_raw)

Información sobre el conjunto de datos

Información general

Los datos corresponden a una variación de un vino tradicional portugués llamado “Vinho Verde” proveniente de una región llamada Vinho, ubicada muy al norte de Portugal.

Variables

  • fixed acidity: ácidos del vino que no se evaporan fácilmente.
  • volatile acidity: cantidad de ácido acético en el vino, el cual en altas cantidades genera sensaciones no placenteras y un sabor vinagroso.
  • citric acid: cantidad de ácido cítrico en pequeñas cantidades, el cual añade cierta frescura y sabor al vino.
  • residual sugar: cantidad de azucar residual luego del proceso de fermentación. Es raro tener menos de 1g/litro y los vinos con más de 45g/litro se consideran dulces.
  • chlorides: cantidad de sal en el vino.
  • free sulfur dioxide: cantidad de dióxido de azufre (S02) libre, el cual previene el crecimiento de microbios y la oxidación del vino.
  • total sulfur dioxide: cantidad total de dióxido de azufre (S02) en forma libre y fija; en bajas concentraciones es indetectable, en concentraciones superiores a 50ppm el SO2 es evidente para la nariz y el sabor del vino.
  • density: la densidad del vino es cercana a la del agua dependiendo de la cantidad de azucar y alcohol.
  • pH: describe qué tan ácido o básico es un vino en un escala desde cero (muy ácido) hasta 14 (muy básico); la gran mayoría de vinos tienen un pH entre 3-4.
  • sulphates: un aditivo que contribuye a regular los niveles de dióxido de azufre (S02), el cual actúa como antimicrobios y antioxidante.
  • alcohol: porcentaje del alcohol del vino.
  • quality: puntuación del vino basada en datos sensoriales, en una escala entre 0 y 10.

Fuente

Cortez, P., Cerdeira, A., Almeida, F., Matos, T., & Reis, J. (2009). Modeling wine preferences by data mining from physicochemical properties. Decision Support Systems, 47(4), 547-553.

Note que es muy importante tener un contexto sobre el conjunto de datos.

Dimensionalidad de los datos

dim(wine_raw)
## [1] 1599   12

Todos los cálculos y procedimientos matemáticos y estadísticos, a nivel computacional, se realizan mediante operaciones sobre las estructuras de datos vistas en la práctica de programación básica.

## Obtener solo el número de filas
nrow(wine_raw)
## [1] 1599
## Obtener solo el número de columnas
ncol(wine_raw)
## [1] 12

Limpieza de los datos

En la práctica la calidad de los datos puede estar afectada por los procesos de captura, sistematización y distribución. Siempre hay que verificar la calidad de nuestros datos.

Para mayor detalle, consulte el material de la practica de limpieza de datos.

En este caso la base de datos proporcionada ya tiene una estructura adecuada para el procesamiento, salvo que los nombres de las columnas tienen espacios y no siguen las convenciones del naming de variavbles, por lo que vamos a ponerles un buen nombre

names(wine_raw) <- str_replace_all(names(wine_raw), c(" " = "_"))

Enriquecimiento de datos

Dado que inicialmente todas las variables son cuantitativas, vamos a realizar una operación sobre nuestro conjunto de datos para agregar dos nuevas columnas categóricas, de tal manera que podemos explorar algunas medidas y gráficas relevantes.

## Partimos de la base de datos 'wine_raw'
## y la ontroducimos a un algoritmo de operaciones
wine_raw %>%
  ## mutate() crea una nueva variable llamada 'calidad'
  ## basada en los rangos ya conocidos de la variable quality
  mutate(
    calidad = ifelse(
      quality == '3' | quality == '4','baja',
      ifelse(
        quality == '5' | quality == '6','media',
        'alta'))
  ) %>% 
  ## mutate_at() recibe la columna 'calidad' y la convierte en un factor
  mutate_at('calidad', factor) %>%
  
  ## mutate() crea una nueva variable llamada 'acetico'
  ## basada en rangos conocidos de la variable 'volatile_acidity'
  mutate(
    acetico = ifelse(volatile_acidity < 0.7, 'bajo', 'alto')
  ) %>% 
  ## mutate_at() recibe la columna 'acetico' y la convierte en un factor
  ## el resultado de todas las operaciones se guarda en 'wine_processed'
  mutate_at('acetico', factor) -> wine_processed

# Especificamos el orden de los factores que acabamos de crear
wine_processed$calidad <- factor(wine_processed$calidad, levels = c("baja","media","alta"))
wine_processed$acetico <- factor(wine_processed$acetico, levels = c("bajo","alto"))

Análisis descriptivo

Resumen numérico

El método summary() que trae por defecto R nos brinda estadísticas de resumen para cada una de las variables de nuestro conjunto de datos.

## Resumen básico de datos
summary(wine_processed)
##  fixed_acidity   volatile_acidity  citric_acid    residual_sugar  
##  Min.   : 4.60   Min.   :0.1200   Min.   :0.000   Min.   : 0.900  
##  1st Qu.: 7.10   1st Qu.:0.3900   1st Qu.:0.090   1st Qu.: 1.900  
##  Median : 7.90   Median :0.5200   Median :0.260   Median : 2.200  
##  Mean   : 8.32   Mean   :0.5278   Mean   :0.271   Mean   : 2.539  
##  3rd Qu.: 9.20   3rd Qu.:0.6400   3rd Qu.:0.420   3rd Qu.: 2.600  
##  Max.   :15.90   Max.   :1.5800   Max.   :1.000   Max.   :15.500  
##    chlorides       free_sulfur_dioxide total_sulfur_dioxide    density      
##  Min.   :0.01200   Min.   : 1.00       Min.   :  6.00       Min.   :0.9901  
##  1st Qu.:0.07000   1st Qu.: 7.00       1st Qu.: 22.00       1st Qu.:0.9956  
##  Median :0.07900   Median :14.00       Median : 38.00       Median :0.9968  
##  Mean   :0.08747   Mean   :15.87       Mean   : 46.47       Mean   :0.9967  
##  3rd Qu.:0.09000   3rd Qu.:21.00       3rd Qu.: 62.00       3rd Qu.:0.9978  
##  Max.   :0.61100   Max.   :72.00       Max.   :289.00       Max.   :1.0037  
##        pH          sulphates         alcohol         quality       calidad    
##  Min.   :2.740   Min.   :0.3300   Min.   : 8.40   Min.   :3.000   baja :  63  
##  1st Qu.:3.210   1st Qu.:0.5500   1st Qu.: 9.50   1st Qu.:5.000   media:1319  
##  Median :3.310   Median :0.6200   Median :10.20   Median :6.000   alta : 217  
##  Mean   :3.311   Mean   :0.6581   Mean   :10.42   Mean   :5.636               
##  3rd Qu.:3.400   3rd Qu.:0.7300   3rd Qu.:11.10   3rd Qu.:6.000               
##  Max.   :4.010   Max.   :2.0000   Max.   :14.90   Max.   :8.000               
##  acetico    
##  bajo:1366  
##  alto: 233  
##             
##             
##             
## 

Resumen gráfico

## Cargamos la librería ggplot2
library(ggplot2)

## Usamos el método para graficar histogramas
## Seleccionamos como objetivo la variable quality
ggplot(wine_processed, aes(quality)) +
    geom_histogram()

Note que podemos hacer histogramas para las demás variables. Además, podríamos realizar otros tipos de gráficos univariados.

Nuestro interés ahora será construir resúmenes numéricos y resúmenes gráficos entre dos o más variables.

Efectos de una variable sobre otra

En una investigación o estudio podemos sospechar de la influencia o efecto de un conjunto de variables sobre una variable particular de interés (target / label / variable crítica / variable explicada). Una parte esencial de la fase de análisis es reunir evidencia para seleccionar las variables que tengan mayor probabilidad de tener un efecto sobre nuestra variable de interés.

Existen distintas herramientas estadísticas para tener una idea bien formada de cómo se relacionan dos o más variables entre sí.

Antes de explorar dichas herramientas, conviene hacer una revisión sobre algunos conceptos.

Asociación entre dos variables contínuas

La covarianza es una medida numérica que nos permite cuantificar la relación (lineal) entre dos variables contínuas.

Su estimador es la covarianza muestral:

  • Si dos variables son independientes su covarianza es nula. El reciproco no es cierto en general, si dos variables tienen covarianza nula se dice que son incorreladas (no hay relación lineal, aunque puede haber una relación no lineal).
  • Si la covarianza es positiva indica que a valores grandes de X le corresponden valores grandes de Y (i.e. al incrementar X se incrementa Y) y se dice que hay una relación lineal positiva.
  • Si la covarianza es negativa indica que a valores grandes de X le corresponden valores pequeños de Y (i.e. al incrementar X, Y disminuye) y se dice que hay una relación lineal negativa.

Cuanto mayor es el valor (absoluto) de la covarianza, mayor es el grado de relación lineal entre las variables. Sin embargo, su valor depende de las escala de las variables por lo que es difícil determinar cuando es grande o pequeña. Para medir el grado de relación lineal puede ser preferible reescalarla, i.e. emplear el coeficiente de correlación:

Su estimador es el coeficiente de correlación muestral:

  • Una correlación positiva entre dos variables indica que a medida que los valores de una variable crecen los valores de la otra variable también crecen. Y viceversa. El máximo valor de una correlación positiva es 1.
  • Una correlación negativa entre dos variables indica que a medida que los valores de una variable crecen los valores de la otra variable decrecen. El máximo valor de una correlación negativa es -1.
  • Una correlación de cero entre dos variables indica que no existe una asociación lineal entre ellas.

Dado que el trabajo estadístico de datos es principalmente matricial y tenemos un número finito de variables aleatorias, en vez de calcular la covarianza entre dos variables podemos construir una matriz de covarianzas y calcular las covarianzas entre todas las variables.

Covarianzas en R

## Covarianzas entre dos variables
cov(wine_processed$fixed_acidity, wine_processed$quality)
## [1] 0.1744236
cov(wine_processed$chlorides, wine_processed$quality)
## [1] -0.004899545
## Matriz de varianzas y covarianzas
## Note que filtramos la base de datos para solamente calcular correlaciones entre variables cuantitativas 
cov(Filter(is.numeric, wine_processed))
##                      fixed_acidity volatile_acidity   citric_acid
## fixed_acidity          3.031416389    -7.985142e-02  0.2278200037
## volatile_acidity      -0.079851417     3.206238e-02 -0.0192716208
## citric_acid            0.227820004    -1.927162e-02  0.0379474831
## residual_sugar         0.281756262     4.841910e-04  0.0394342700
## chlorides              0.007678692     5.165869e-04  0.0018687248
## free_sulfur_dioxide   -2.800921493    -1.967359e-02 -0.1242521139
## total_sulfur_dioxide  -6.482345858     4.504257e-01  0.2276972740
## density                0.002195224     7.443665e-06  0.0001341746
## pH                    -0.183585704     6.494699e-03 -0.0162975823
## sulphates              0.054010092    -7.921434e-03  0.0103277145
## alcohol               -0.114421153    -3.860022e-02  0.0228151729
## quality                0.174423588    -5.647588e-02  0.0356118929
##                      residual_sugar     chlorides free_sulfur_dioxide
## fixed_acidity          0.2817562623  7.678692e-03       -2.800921e+00
## volatile_acidity       0.0004841910  5.165869e-04       -1.967359e-02
## citric_acid            0.0394342700  1.868725e-03       -1.242521e-01
## residual_sugar         1.9878971330  3.690176e-03        2.758611e+00
## chlorides              0.0036901759  2.215143e-03        2.738303e-03
## free_sulfur_dioxide    2.7586114522  2.738303e-03        1.094149e+02
## total_sulfur_dioxide   9.4164414790  7.338675e-02        2.297375e+02
## density                0.0009454109  1.782176e-05       -4.332504e-04
## pH                    -0.0186442890 -1.925745e-03        1.136531e-01
## sulphates              0.0013209414  2.961878e-03        9.159247e-02
## alcohol                0.0632189598 -1.109152e-02       -7.736984e-01
## quality                0.0156350457 -4.899545e-03       -4.279071e-01
##                      total_sulfur_dioxide       density            pH
## fixed_acidity               -6.482346e+00  2.195224e-03 -1.835857e-01
## volatile_acidity             4.504257e-01  7.443665e-06  6.494699e-03
## citric_acid                  2.276973e-01  1.341746e-04 -1.629758e-02
## residual_sugar               9.416441e+00  9.454109e-04 -1.864429e-02
## chlorides                    7.338675e-02  1.782176e-05 -1.925745e-03
## free_sulfur_dioxide          2.297375e+02 -4.332504e-04  1.136531e-01
## total_sulfur_dioxide         1.082102e+03  4.424727e-03 -3.376988e-01
## density                      4.424727e-03  3.562029e-06 -9.956395e-05
## pH                          -3.376988e-01 -9.956395e-05  2.383518e-02
## sulphates                    2.394710e-01  4.750962e-05 -5.146186e-03
## alcohol                     -7.209298e+00 -9.979518e-04  3.383162e-02
## quality                     -4.917237e+00 -2.666037e-04 -7.197822e-03
##                          sulphates       alcohol       quality
## fixed_acidity         5.401009e-02 -0.1144211534  0.1744235876
## volatile_acidity     -7.921434e-03 -0.0386002214 -0.0564758833
## citric_acid           1.032771e-02  0.0228151729  0.0356118929
## residual_sugar        1.320941e-03  0.0632189598  0.0156350457
## chlorides             2.961878e-03 -0.0110915178 -0.0048995449
## free_sulfur_dioxide   9.159247e-02 -0.7736984004 -0.4279070696
## total_sulfur_dioxide  2.394710e-01 -7.2092978950 -4.9172370717
## density               4.750962e-05 -0.0009979518 -0.0002666037
## pH                   -5.146186e-03  0.0338316166 -0.0071978223
## sulphates             2.873262e-02  0.0169067772  0.0344134084
## alcohol               1.690678e-02  1.1356473950  0.4097890108
## quality               3.441341e-02  0.4097890108  0.6521684000

Correlaciones en R

## Correlaciones entre dos variables
cor(wine_processed$fixed_acidity, wine_processed$quality, method = 'pearson')
## [1] 0.1240516
cor(wine_processed$chlorides, wine_processed$quality, method = 'pearson')
## [1] -0.1289066
## Matriz de correlaciones
## Note que filtramos la base de datos para solamente calcular correlaciones entre variables cuantitativas
cor(Filter(is.numeric, wine_processed), method = 'pearson')
##                      fixed_acidity volatile_acidity citric_acid residual_sugar
## fixed_acidity           1.00000000     -0.256130895  0.67170343    0.114776724
## volatile_acidity       -0.25613089      1.000000000 -0.55249568    0.001917882
## citric_acid             0.67170343     -0.552495685  1.00000000    0.143577162
## residual_sugar          0.11477672      0.001917882  0.14357716    1.000000000
## chlorides               0.09370519      0.061297772  0.20382291    0.055609535
## free_sulfur_dioxide    -0.15379419     -0.010503827 -0.06097813    0.187048995
## total_sulfur_dioxide   -0.11318144      0.076470005  0.03553302    0.203027882
## density                 0.66804729      0.022026232  0.36494718    0.355283371
## pH                     -0.68297819      0.234937294 -0.54190414   -0.085652422
## sulphates               0.18300566     -0.260986685  0.31277004    0.005527121
## alcohol                -0.06166827     -0.202288027  0.10990325    0.042075437
## quality                 0.12405165     -0.390557780  0.22637251    0.013731637
##                         chlorides free_sulfur_dioxide total_sulfur_dioxide
## fixed_acidity         0.093705186        -0.153794193          -0.11318144
## volatile_acidity      0.061297772        -0.010503827           0.07647000
## citric_acid           0.203822914        -0.060978129           0.03553302
## residual_sugar        0.055609535         0.187048995           0.20302788
## chlorides             1.000000000         0.005562147           0.04740047
## free_sulfur_dioxide   0.005562147         1.000000000           0.66766645
## total_sulfur_dioxide  0.047400468         0.667666450           1.00000000
## density               0.200632327        -0.021945831           0.07126948
## pH                   -0.265026131         0.070377499          -0.06649456
## sulphates             0.371260481         0.051657572           0.04294684
## alcohol              -0.221140545        -0.069408354          -0.20565394
## quality              -0.128906560        -0.050656057          -0.18510029
##                          density          pH    sulphates     alcohol
## fixed_acidity         0.66804729 -0.68297819  0.183005664 -0.06166827
## volatile_acidity      0.02202623  0.23493729 -0.260986685 -0.20228803
## citric_acid           0.36494718 -0.54190414  0.312770044  0.10990325
## residual_sugar        0.35528337 -0.08565242  0.005527121  0.04207544
## chlorides             0.20063233 -0.26502613  0.371260481 -0.22114054
## free_sulfur_dioxide  -0.02194583  0.07037750  0.051657572 -0.06940835
## total_sulfur_dioxide  0.07126948 -0.06649456  0.042946836 -0.20565394
## density               1.00000000 -0.34169933  0.148506412 -0.49617977
## pH                   -0.34169933  1.00000000 -0.196647602  0.20563251
## sulphates             0.14850641 -0.19664760  1.000000000  0.09359475
## alcohol              -0.49617977  0.20563251  0.093594750  1.00000000
## quality              -0.17491923 -0.05773139  0.251397079  0.47616632
##                          quality
## fixed_acidity         0.12405165
## volatile_acidity     -0.39055778
## citric_acid           0.22637251
## residual_sugar        0.01373164
## chlorides            -0.12890656
## free_sulfur_dioxide  -0.05065606
## total_sulfur_dioxide -0.18510029
## density              -0.17491923
## pH                   -0.05773139
## sulphates             0.25139708
## alcohol               0.47616632
## quality               1.00000000

Por defecto el método cor() calcula una correlación de Pearson, por tanto, el resultado numerico asume que la relación entre las variables es lineal. Dado que en la practica hay muchas relaciones no lineales, una forma más robusta de calcular la asociación es calculando una correlación de Spearman (method = ‘spearman’) o el estadístico Tau de Kendall (method = ‘kendall’).

Otra forma más bonita de mostrar correlaciones usando el paquete correlation

# Instalamos el paquete correlation
install.packages("correlation")
# Creamos una matriz detallada de correlaciones
# Note que acá no estamos filtrando las columnas numéricas como lo hicimos antes
# Esto debido a que el paquete automáticamente hace el filtrado. Uno debe verificar
correlaciones <- correlation(wine_processed)
correlaciones
## # Correlation Matrix (pearson-method)
## 
## Parameter1           |           Parameter2 |        r |         95% CI | t(1597) |         p
## ---------------------------------------------------------------------------------------------
## fixed_acidity        |     volatile_acidity |    -0.26 | [-0.30, -0.21] |  -10.59 | < .001***
## fixed_acidity        |          citric_acid |     0.67 | [ 0.64,  0.70] |   36.23 | < .001***
## fixed_acidity        |       residual_sugar |     0.11 | [ 0.07,  0.16] |    4.62 | < .001***
## fixed_acidity        |            chlorides |     0.09 | [ 0.04,  0.14] |    3.76 | 0.005**  
## fixed_acidity        |  free_sulfur_dioxide |    -0.15 | [-0.20, -0.11] |   -6.22 | < .001***
## fixed_acidity        | total_sulfur_dioxide |    -0.11 | [-0.16, -0.06] |   -4.55 | < .001***
## fixed_acidity        |              density |     0.67 | [ 0.64,  0.69] |   35.88 | < .001***
## fixed_acidity        |                   pH |    -0.68 | [-0.71, -0.66] |  -37.37 | < .001***
## fixed_acidity        |            sulphates |     0.18 | [ 0.14,  0.23] |    7.44 | < .001***
## fixed_acidity        |              alcohol |    -0.06 | [-0.11, -0.01] |   -2.47 | 0.246    
## fixed_acidity        |              quality |     0.12 | [ 0.08,  0.17] |    5.00 | < .001***
## volatile_acidity     |          citric_acid |    -0.55 | [-0.59, -0.52] |  -26.49 | < .001***
## volatile_acidity     |       residual_sugar | 1.92e-03 | [-0.05,  0.05] |    0.08 | > .999   
## volatile_acidity     |            chlorides |     0.06 | [ 0.01,  0.11] |    2.45 | 0.246    
## volatile_acidity     |  free_sulfur_dioxide |    -0.01 | [-0.06,  0.04] |   -0.42 | > .999   
## volatile_acidity     | total_sulfur_dioxide |     0.08 | [ 0.03,  0.13] |    3.06 | 0.051    
## volatile_acidity     |              density |     0.02 | [-0.03,  0.07] |    0.88 | > .999   
## volatile_acidity     |                   pH |     0.23 | [ 0.19,  0.28] |    9.66 | < .001***
## volatile_acidity     |            sulphates |    -0.26 | [-0.31, -0.21] |  -10.80 | < .001***
## volatile_acidity     |              alcohol |    -0.20 | [-0.25, -0.15] |   -8.25 | < .001***
## volatile_acidity     |              quality |    -0.39 | [-0.43, -0.35] |  -16.95 | < .001***
## citric_acid          |       residual_sugar |     0.14 | [ 0.10,  0.19] |    5.80 | < .001***
## citric_acid          |            chlorides |     0.20 | [ 0.16,  0.25] |    8.32 | < .001***
## citric_acid          |  free_sulfur_dioxide |    -0.06 | [-0.11, -0.01] |   -2.44 | 0.246    
## citric_acid          | total_sulfur_dioxide |     0.04 | [-0.01,  0.08] |    1.42 | > .999   
## citric_acid          |              density |     0.36 | [ 0.32,  0.41] |   15.66 | < .001***
## citric_acid          |                   pH |    -0.54 | [-0.58, -0.51] |  -25.77 | < .001***
## citric_acid          |            sulphates |     0.31 | [ 0.27,  0.36] |   13.16 | < .001***
## citric_acid          |              alcohol |     0.11 | [ 0.06,  0.16] |    4.42 | < .001***
## citric_acid          |              quality |     0.23 | [ 0.18,  0.27] |    9.29 | < .001***
## residual_sugar       |            chlorides |     0.06 | [ 0.01,  0.10] |    2.23 | 0.366    
## residual_sugar       |  free_sulfur_dioxide |     0.19 | [ 0.14,  0.23] |    7.61 | < .001***
## residual_sugar       | total_sulfur_dioxide |     0.20 | [ 0.16,  0.25] |    8.29 | < .001***
## residual_sugar       |              density |     0.36 | [ 0.31,  0.40] |   15.19 | < .001***
## residual_sugar       |                   pH |    -0.09 | [-0.13, -0.04] |   -3.44 | 0.015*   
## residual_sugar       |            sulphates | 5.53e-03 | [-0.04,  0.05] |    0.22 | > .999   
## residual_sugar       |              alcohol |     0.04 | [-0.01,  0.09] |    1.68 | 0.860    
## residual_sugar       |              quality |     0.01 | [-0.04,  0.06] |    0.55 | > .999   
## chlorides            |  free_sulfur_dioxide | 5.56e-03 | [-0.04,  0.05] |    0.22 | > .999   
## chlorides            | total_sulfur_dioxide |     0.05 | [ 0.00,  0.10] |    1.90 | 0.639    
## chlorides            |              density |     0.20 | [ 0.15,  0.25] |    8.18 | < .001***
## chlorides            |                   pH |    -0.27 | [-0.31, -0.22] |  -10.98 | < .001***
## chlorides            |            sulphates |     0.37 | [ 0.33,  0.41] |   15.98 | < .001***
## chlorides            |              alcohol |    -0.22 | [-0.27, -0.17] |   -9.06 | < .001***
## chlorides            |              quality |    -0.13 | [-0.18, -0.08] |   -5.19 | < .001***
## free_sulfur_dioxide  | total_sulfur_dioxide |     0.67 | [ 0.64,  0.69] |   35.84 | < .001***
## free_sulfur_dioxide  |              density |    -0.02 | [-0.07,  0.03] |   -0.88 | > .999   
## free_sulfur_dioxide  |                   pH |     0.07 | [ 0.02,  0.12] |    2.82 | 0.102    
## free_sulfur_dioxide  |            sulphates |     0.05 | [ 0.00,  0.10] |    2.07 | 0.505    
## free_sulfur_dioxide  |              alcohol |    -0.07 | [-0.12, -0.02] |   -2.78 | 0.110    
## free_sulfur_dioxide  |              quality |    -0.05 | [-0.10,  0.00] |   -2.03 | 0.514    
## total_sulfur_dioxide |              density |     0.07 | [ 0.02,  0.12] |    2.86 | 0.096    
## total_sulfur_dioxide |                   pH |    -0.07 | [-0.12, -0.02] |   -2.66 | 0.149    
## total_sulfur_dioxide |            sulphates |     0.04 | [-0.01,  0.09] |    1.72 | 0.860    
## total_sulfur_dioxide |              alcohol |    -0.21 | [-0.25, -0.16] |   -8.40 | < .001***
## total_sulfur_dioxide |              quality |    -0.19 | [-0.23, -0.14] |   -7.53 | < .001***
## density              |                   pH |    -0.34 | [-0.38, -0.30] |  -14.53 | < .001***
## density              |            sulphates |     0.15 | [ 0.10,  0.20] |    6.00 | < .001***
## density              |              alcohol |    -0.50 | [-0.53, -0.46] |  -22.84 | < .001***
## density              |              quality |    -0.17 | [-0.22, -0.13] |   -7.10 | < .001***
## pH                   |            sulphates |    -0.20 | [-0.24, -0.15] |   -8.02 | < .001***
## pH                   |              alcohol |     0.21 | [ 0.16,  0.25] |    8.40 | < .001***
## pH                   |              quality |    -0.06 | [-0.11, -0.01] |   -2.31 | 0.314    
## sulphates            |              alcohol |     0.09 | [ 0.04,  0.14] |    3.76 | 0.005**  
## sulphates            |              quality |     0.25 | [ 0.20,  0.30] |   10.38 | < .001***
## alcohol              |              quality |     0.48 | [ 0.44,  0.51] |   21.64 | < .001***
## 
## p-value adjustment method: Holm (1979)
## Observations: 1599

Que exista una asociación fuerte entre dos variables no implica una relación causal. Para testear la causalidad veremos otras herramientas más adelante.

Visualización de la relación entre variables

Hemos visto que podemos crear gráficos univariados para tener una fotografía del comportamiento de una variable. De igual manera, es posible construir gráficos que muestren la asociación entre dos o más variables.

Variable 1 Variable 2 Visualización frecuente
Categórica Categórica Tablas de contingencia
Categórica Contínua Boxplot por grupos
Contínua Contínua Diagrama de dispersión

Para nuestro ejemplo del vino rojo, siguiendo las recomendaciones de la tabla, conviene crear diagramas de dispersión.

Diagrama de dispersión

Son útiles porque al cruzar los valores de un par de variables podemos encontrar posibles relaciones matemáticas entre ellas.

# install.packages("hrbrthemes")
library(hrbrthemes)

## Una relación lineal inexistente
ggplot(wine_processed, aes(x=residual_sugar, y=quality)) +
  geom_point() +
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_ipsum()

## Una relación lineal positiva
ggplot(wine_processed, aes(x=alcohol, y=quality)) +
  geom_point() +
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_ipsum()

## Una relación lineal negativa
ggplot(wine_processed, aes(x=volatile_acidity, y=quality)) +
  geom_point() +
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_ipsum()

Correlogramas

Podemos crear una visualización donde se muestren todos los posibles diagramas de dispersión entre parejas de variables con sus respectivos coeficientes de correlación.

## Instalamos la librería GGally
install.packages('GGally')
## Cargamos la librería
library('GGally')

## Creamos la visualización usando el método ggpairs()
ggpairs(
  wine_processed, 
  title="Correlograma"
  ) 

Podemos graficar filtrando ciertas variables de interés. En este caso, vamos a remover aquellas que tengan un coeficiente de correlación menor a 0.2 con nuestra variable target (quality).

## Declaramos un vector con nuestras variables de interés
var_interes = c('volatile_acidity','citric_acid','sulphates','alcohol','quality')

## Creamos la visualización usando el método ggpairs() agregando el parámetro columns
ggpairs(
  wine_processed, 
  title="Correlograma",
  columns = var_interes
  ) 

Otra forma de visualizar la correlación entre variables.

ggcorr(
  Filter(is.numeric, wine_processed), 
  method = c("everything", "pearson"),
  size = 3
  )

De las anteriores matrices y gráficas podemos observar algunas nuevas correlaciones de interés, por ejemplo, entre el pH y la acidéz. Podemos observar además que para la variable target aproximadamente la mitad de las variables independientes correlacionan positivamente y la otra mitad negativamente.

En la práctica, se pueden seleccionar las variables independientes que tienen las medidas de asociación más altas en la medida que sospechamos que nos aportan más información. Una regla de oro sencilla es excluir variables que tengan una correlación menor (en valor absoluto) a 0.2.

Examen detallado de variables de interés

De nuestro conjunto de datos iniciales hemos detectado ciertas variables independientes o explicativas que nos pueden aportar mayor información para explicar la calidad del vino.

  • volatile_acidity
  • citric_acid
  • sulphates
  • alcohol

Adicionalmente, tenemos la calidad del vino expresada como una variable contínua (quality) y también de forma categórica (calidad).

¿Qué deberíamos hacer? Analizar el comportamiento conjunto de cada una de nuestras variables explicativas con la variable crítica. Dicho esto, vamos ahora a realizar estos cruces bivariados en tres escenarios:

Escenario 1: Asociación entre dos variables contínuas

Ya vimos cómo hacer el cálculo de coeficientes de correlación. Examinemos ahora en diagramas de dispersión las relaciones entre las variables de interés y la variable crítica cuantitativa quality.

Al ver los diagramas de dispersión, ¿es plausible pensar que hay una relación entre las variables?

volatile_acidity

ggplot(wine_processed, aes(x=volatile_acidity, y=quality)) +
  geom_point() +
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_ipsum()

citric_acid

ggplot(wine_processed, aes(x=citric_acid, y=quality)) +
  geom_point() +
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_ipsum()

sulphates

ggplot(wine_processed, aes(x=sulphates, y=quality)) +
  geom_point() +
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_ipsum()

alcohol

ggplot(wine_processed, aes(x=alcohol, y=quality)) +
  geom_point() +
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_ipsum()

En nuestro conjunto de datos original todas las variables son contínuas. El cálculo de medidas de resumen bivariadas como las covarianzas o coeficientes de correlación, así como los resúmenes gráficos vistos, nos permiten tener una idea bien formada de si existen relaciones entre las variables y el sentido de dichas relaciones.

Escenario 2: Asociación entre una variable categórica y una variable contínua

En este escenario no podemos calcular covarianzas ni correlaciones de Pearson, luego debemos disponer de otro conjunto de herramientas para testear las relaciones entre las variables.

  • Correlación biserial-puntual
  • Regresión logística
  • Prueba de Kruskall-Wallis
  • Entre otras

Por facilidad, haremos una prueba de Kruskall-Wallis cuyo p-valor testeará la hipótesis de si existe una relación significante entre las variables.

  • Hipótesis nula: las variables son independientes.
  • Hipótesis alternativa: las variables no son independientes (puede existir un efecto causal).
kruskal.test(wine_processed$volatile_acidity, wine_processed$calidad)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  wine_processed$volatile_acidity and wine_processed$calidad
## Kruskal-Wallis chi-squared = 168.44, df = 2, p-value < 2.2e-16
kruskal.test(wine_processed$citric_acid, wine_processed$calidad)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  wine_processed$citric_acid and wine_processed$calidad
## Kruskal-Wallis chi-squared = 86.083, df = 2, p-value < 2.2e-16
kruskal.test(wine_processed$sulphates, wine_processed$calidad)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  wine_processed$sulphates and wine_processed$calidad
## Kruskal-Wallis chi-squared = 147.44, df = 2, p-value < 2.2e-16
kruskal.test(wine_processed$alcohol, wine_processed$calidad)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  wine_processed$alcohol and wine_processed$calidad
## Kruskal-Wallis chi-squared = 234.32, df = 2, p-value < 2.2e-16

Visualización de las relaciones

En este caso podemos construir boxplot por grupos para cruzar la variable crítica calidad con las variables de interés.

ggplot(data = wine_processed) +
  aes(x = calidad, y = volatile_acidity) +
  geom_boxplot(fill = "#0c4c8a") +
  theme_minimal()

ggplot(data = wine_processed) +
  aes(x = calidad, y = citric_acid) +
  geom_boxplot(fill = "#0c4c8a") +
  theme_minimal()

ggplot(data = wine_processed) +
  aes(x = calidad, y = sulphates) +
  geom_boxplot(fill = "#0c4c8a") +
  theme_minimal()

ggplot(data = wine_processed) +
  aes(x = calidad, y = alcohol) +
  geom_boxplot(fill = "#0c4c8a") +
  theme_minimal()

Escenario 3: Asociación entre dos variables categóricas

En este caso conviene hacer análisis mediante tablas de contingencia, las cuales cuentan las frecuencias observadas en cada categoría.

tbl = table(wine_processed$acetico, wine_processed$calidad) 
tbl
##       
##        baja media alta
##   bajo   34  1122  210
##   alto   29   197    7
# Damos nombre a las columnas y las filas 
colnames(tbl) <- c("Calidad baja", "Calidad media", "Calidad alta")
rownames(tbl) <- c("Ácido acético bajo","Ácido acético alto")
tbl
##                     
##                      Calidad baja Calidad media Calidad alta
##   Ácido acético bajo           34          1122          210
##   Ácido acético alto           29           197            7

Al tener conformada la tabla de contingencia, la forma de revisar si existe una asociación entre las variables es por medio de una prueba de independencia X2 (Chi-Cuadrado).

La prueba indicará si dos características son independientes o tienen una asociación, de manera que las frecuencias elevadas en una de ellas suele ser acompañado con frecuencias altas en la otra.

  • Hipótesis nula: las columnas y las filas de la tabla son independientes.
  • Hipótesis alternativa: las columnas y las filas son dependientes (puede existir un efecto causal).
## Prueba Chi-Cuadrado
chisq.test(tbl)
## 
##  Pearson's Chi-squared test
## 
## data:  tbl
## X-squared = 72.67, df = 2, p-value < 2.2e-16

Observaciones de cierre

Identificar las relaciones existentes entre dos o más variables es parte arte y parte ciencia, por lo que se recomienda ganar experiencia leyendo articulos cientificos y viendo soluciones a diversos problemas.

Además,

  1. Hay que procurar trabajar con variables informativas, es decir, que guarden una relación con la variable objetivo.
  2. Hay que evitar las redundancias, luego lo ideal es que nuestras variables explicativas/independientes/features sean independientes entre sí.
  3. Nuestra intuición puede fallar en dimensiones superiores a 3. En la mayoría de los casos aumentar la cantidad de variables afecta negativamente el entendimiento de un problema si no contamos con una gran cantidad de datos. Por ultimo, una cantidad controlada de variables asegura una mejor interpretabilidad de los análisis y modelos.